package com.pg.face.pgface.untils;

import com.alibaba.fastjson.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

/**
 * 全局统一异常拦截处理类
 *
 * @author xujunqi
 * @date 2019/1/28 15:06
 */
@RestControllerAdvice
public class BaseRest {

    private final static Logger LOGGER = LoggerFactory.getLogger(BaseRest.class);

    @ExceptionHandler(Exception.class)
    public <T> ResponseEntity<ResponseMsg<T>> handleGlobalException(Exception ex) {
        LOGGER.info("全局统一异常拦截到运行时异常信息: {}", ex.getMessage(), ex);
        ResponseMsg responseMsg = new ResponseMsg<T>();

        responseMsg.setRetCode(GlobalResponseStatusEnum.ERROR.getCode());
        responseMsg.setRetDesc(GlobalResponseStatusEnum.ERROR.getName());
        ResponseEntity responseEntity = new ResponseEntity<ResponseMsg<T>>(responseMsg, HttpStatus.OK);
        return responseEntity;
    }

    @ExceptionHandler(JSONException.class)
    public <T> ResponseEntity<ResponseMsg<T>> handleJsonException(JSONException ex) {
        StringBuilder errorMesssage = new StringBuilder(GlobalResponseStatusEnum.INVALID_PARAM_DATA_BIND.getName()).append(": [").append(ex.getMessage()).append("]");

        LOGGER.info("请求参数转换异常, 请核实请求参数格式: [{}]", ex.getMessage());
        ResponseMsg responseMsg = new ResponseMsg<T>();

        responseMsg.setRetCode(GlobalResponseStatusEnum.INVALID_PARAM_DATA_BIND.getCode());
        responseMsg.setRetDesc(errorMesssage.toString());
        ResponseEntity responseEntity = new ResponseEntity<ResponseMsg<T>>(responseMsg, HttpStatus.OK);
        return responseEntity;
    }


    @ExceptionHandler(MethodArgumentNotValidException.class)
    public <T> ResponseEntity<ResponseMsg<T>> handleInvalidException(MethodArgumentNotValidException ex) {
        BindingResult bindingResult = ex.getBindingResult();

        StringBuilder errorMesssage = new StringBuilder(GlobalResponseStatusEnum.INVALID_PARAM.getName()).append(": [");

        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            errorMesssage.append("{").append(fieldError.getField()).append(": ").append(fieldError.getDefaultMessage()).append("}; ");
        }
        errorMesssage.append("]");

        LOGGER.info("请求参数校验异常: [{}]", errorMesssage.toString());
        ResponseMsg responseMsg = new ResponseMsg<T>();

        responseMsg.setRetCode(GlobalResponseStatusEnum.INVALID_PARAM.getCode());
        responseMsg.setRetDesc(errorMesssage.toString());
        ResponseEntity responseEntity = new ResponseEntity<ResponseMsg<T>>(responseMsg, HttpStatus.OK);
        return responseEntity;
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public <T> ResponseEntity<ResponseMsg<T>> handleValidationException(ConstraintViolationException ex) {
        StringBuilder errorMesssage = new StringBuilder(GlobalResponseStatusEnum.INVALID_PARAM.getName()).append(": [");

        for (ConstraintViolation<?> s : ex.getConstraintViolations()) {
            errorMesssage.append("{").append(s.getMessage()).append("}; ");
        }
        errorMesssage.append("]");

        LOGGER.info("请求参数转换异常, 请核实请求参数格式: [{}]", ex.getMessage());
        ResponseMsg responseMsg = new ResponseMsg<T>();

        responseMsg.setRetCode(GlobalResponseStatusEnum.INVALID_PARAM.getCode());
        responseMsg.setRetDesc(errorMesssage.toString());
        ResponseEntity responseEntity = new ResponseEntity<ResponseMsg<T>>(responseMsg, HttpStatus.OK);
        return responseEntity;
    }

    @ExceptionHandler(RRException.class)
    public <T> ResponseEntity<ResponseMsg<T>> handleAntfException(RRException ex) {
        LOGGER.info("RRException===业务异常: [{}]", ex.getMessage());
        ResponseMsg responseMsg = new ResponseMsg<T>();

        responseMsg.setRetCode(GlobalResponseStatusEnum.FAILURE.getCode());
        if(ex.getMessage() != null && ex.getMessage().contains("token")){
            responseMsg.setRetCode(GlobalResponseStatusEnum.UNLOGIN.getCode());
        }
        responseMsg.setRetDesc(ex.getMessage());
        return new ResponseEntity<ResponseMsg<T>>(responseMsg, HttpStatus.OK);
    }

    @ResponseStatus(HttpStatus.NOT_MODIFIED)//返回304状态码
    @ResponseBody
    @ExceptionHandler(AsyncRequestTimeoutException.class) //捕获特定异常
    public void handleAsyncRequestTimeoutException(AsyncRequestTimeoutException e, HttpServletRequest request) {
        System.out.println("error==============handleAsyncRequestTimeoutException");
    }


}

